package src.main.java;

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: ws
 * Date: 2023-12-27
 * Time: 14:00
 */
public class T6 {

    public static void main(String[] args) throws Throwable {
        /**
         * 虚拟机配置选项
         * VM Options ：-XX:+PrintGCDetails -Xms10m -Xmx10m
         * -XX:+PrintGCDetails：打印 GC 的详细信息
         * -Xms10m：设置初始化堆空间大小为 10m
         * -Xmx10m：设置最大堆空间大小为 10m
         */
        // 强引用
        // 开一个 4m（即 4096k）大小的 byte 数组（实际可能大于 4m，但是不会相差太多）
//        byte[] bytes = new byte[4 * 1024 * 1024];
//        // 调用 GC
//        System.gc();


        /**
         * 虚拟机配置选项
         * VM Options ：-XX:+PrintGCDetails -Xms10m -Xmx10m
         * -XX:+PrintGCDetails：打印 GC 的详细信息
         * -Xms10m：设置初始化堆空间大小为 10m
         * -Xmx10m：设置最大堆空间大小为 10m
         */
        // 软引用
//        Map<String, SoftReference<byte[]>> map = new HashMap<>();
//        // 最大 10m 的堆空间肯定装不 24m 的数组，所以 JVM 会自动 GC 回收
//        map.put("bytes1", new SoftReference<>(new byte[6 * 1024 * 1024]));
//        map.put("bytes2", new SoftReference<>(new byte[6 * 1024 * 1024]));
//        map.put("bytes3", new SoftReference<>(new byte[6 * 1024 * 1024]));
//        // 强引用数组，无法回收
//        byte[] bytes2 = new byte[6 * 1024 * 1024];


        // 弱引用

//        Object o1 = new Object();
//        ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
//        // 弱引用加入到引用队列
//        WeakReference<Object> weakReference = new WeakReference<>(o1, referenceQueue);
//
//
//        System.out.println(o1);
//        System.out.println(weakReference.get());
//        System.out.println(referenceQueue.poll());
        /**
         * 发生 GC 之前
         * java.lang.Object@1b6d3586
         * java.lang.Object@1b6d3586
         * null // 引用队列中不存储对象
         */

        // 将该对象置空
//        o1 = null;
//
//        System.gc();
//        Thread.sleep(500);
//
//        System.out.println(o1);
//        System.out.println(weakReference.get());
//        System.out.println(weakReference);
//        System.out.println(referenceQueue.poll());
        /** GC 之后
         * null 对象为空
         * null 弱引用中存储的对象为空
         * java.lang.ref.WeakReference@4554617c 弱引用对象还在
         * java.lang.ref.WeakReference@4554617c 该弱引用对象放到了引用队列中
         */


        // 虚引用
        // 作用：监控对象的回收情况

        // 要监控的对象
        Object o1 = new Object();
        // 引用队列
        ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();
        // 虚引用绑定对象和引用队列
        PhantomReference<Object> phantomReference = new PhantomReference<>(o1, referenceQueue);

        // 回收前的被监控的对象
        System.out.println("回收前的被监控的对象: " + o1);
        // 虚引用地址
        System.out.println("虚引用地址: " + phantomReference);
        // 源码可知，总是返回 null
        System.out.println("虚引用的返回值: " + phantomReference.get());
        // 所以队列也返回 null
        System.out.println("引用队列的返回值: " + referenceQueue.poll());

        System.out.println("====================");
        // 置空监控的对象
        o1 = null;
        // 回收对象
        System.gc();
        // 监控的对象
        System.out.println("回收后的对象: " +o1);
        // 虚引用地址
        System.out.println( "虚引用地址: " + phantomReference);
        // 源码可知，总是返回 null
        System.out.println("虚引用的返回值: " + phantomReference.get());
        // 重点！！！！！
        // 引用队列中存储了虚引用，说明该对象被回收了
        // 这就是虚引用的唯一目的，即 gc 后将自身加入到引用队列
        System.out.println("引用队列的返回值: " + referenceQueue.poll());
    }
}
